package com.wasp.collector.service;

import java.io.IOException;
import java.nio.charset.Charset;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.wasp.collector.content.Content;
import com.wasp.collector.data.RequestContext;
import com.wasp.collector.data.RequestWrapper;
import com.wasp.collector.utils.CharsetUtils;

public class HttpClientExecutor {
	private static final Logger log = LoggerFactory.getLogger(HttpClientExecutor.class);
	private RequestWrapper wrapper;
	private RequestContext context ;
	public HttpClientExecutor(RequestWrapper wrapper,RequestContext context) {
		this.wrapper = wrapper;
		this.context = context;
	}

	public Content exec(){
		HttpClientCollector collector = new HttpClientCollector(wrapper);
		CloseableHttpClient client = collector.build();
		DoRequest doRequest = new DoRequest(context, wrapper);
		HttpUriRequest request = doRequest.create();
		log.info(request.getURI().toString());
		try {
			CloseableHttpResponse httpResponse = client.execute(request);
			int statusCode = httpResponse.getStatusLine().getStatusCode();
			if(statusCode == 200){
				Content page = handleResponse(request, 
						wrapper.getCharset(),
	            		httpResponse);
	            return page;
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		return null;
	}

	protected Content handleResponse(HttpUriRequest request, String charset, CloseableHttpResponse httpResponse)
			throws IOException {
		String contentText = getResponseContent(charset, httpResponse);
		Content page = new Content();
		page.setRawContent(contentText);
		page.setRequestContext(context);
		page.setStatus(httpResponse.getStatusLine().getStatusCode());
		return page;
	}

	private String getResponseContent(String charset, CloseableHttpResponse httpResponse) throws IOException {
		if (charset == null) {
			byte[] contentBytes = IOUtils.toByteArray(httpResponse.getEntity().getContent());
			String htmlCharset = getHtmlCharset(httpResponse, contentBytes);
			if (htmlCharset != null) {
				return new String(contentBytes, htmlCharset);
			} else {
				log.info("Charset autodetect failed, use {} as charset. Please specify charset in Site.setCharset()"+Charset.defaultCharset());
				return new String(contentBytes);
			}
		} else {
			return IOUtils.toString(httpResponse.getEntity().getContent(), charset);
		}
	}

	private String getHtmlCharset(HttpResponse httpResponse, byte[] contentBytes) throws IOException {
		return CharsetUtils.detectCharset(httpResponse.getEntity().getContentType().getValue(), contentBytes);
	}
}